/*
 * HTView.java www.bouthier.net The MIT License : ----------------- Copyright
 * (c) 2001 Christophe Bouthier Permission is hereby granted, free of charge, to
 * any person obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to permit
 * persons to whom the Software is furnished to do so, subject to the following
 * conditions: The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software. THE SOFTWARE
 * IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
 * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

package hypertree.model;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;

import javax.swing.JPanel;
import javax.swing.ToolTipManager;

/**
 * The HTView class implements a view of the HyperTree.
 * 
 * @author Christophe Bouthier [bouthier@loria.fr]
 * @version 1.0
 */
public class HTView extends JPanel
{

	private static final long	serialVersionUID	= 4266727463658428796L;
	@SuppressWarnings("unused")
	private HTModel				model				= null;				// the
	// tree
	// model
	// represented
	private HTDraw				draw				= null;				// the
	// drawing
	// model
	private HTAction			action				= null;				// action

	// manager

	/* --- Constructor --- */

	/**
	 * Constructor.
	 * 
	 * @param model
	 *            the tree model to view
	 */
	public HTView(HTModel model)
	{
		super(new BorderLayout());
		this.setPreferredSize(new Dimension(500, 500));
		this.setBackground(Color.white);

		this.model = model;
		this.draw = new HTDraw(model, this);
		this.action = new HTAction(this.draw);
		this.startMouseListening();
		ToolTipManager.sharedInstance().registerComponent(this);
	}

	/* --- Node finding --- */

	/**
	 * Returns the node containing the mouse event.
	 * <P>
	 * This will be a HTNode.
	 * 
	 * @param event
	 *            the mouse event on a node
	 * @return the node containing this event; could be <CODE>null</CODE> if
	 *         no node was found
	 */
	public Object getNodeUnderTheMouse(MouseEvent event)
	{
		int x = event.getX();
		int y = event.getY();

		HTDrawNode node = this.draw.findNode(new HTCoordS(x, y));
		if (node != null)
		{
			return node.getHTModelNode().getNode();
		}
		else
		{
			return null;
		}
	}

	/* --- Tooltip --- */

	/**
	 * Returns the tooltip to be displayed.
	 * 
	 * @param event
	 *            the event triggering the tooltip
	 * @return the String to be displayed
	 */
	@Override
	public String getToolTipText(MouseEvent event)
	{
		int x = event.getX();
		int y = event.getY();

		HTDrawNode node = this.draw.findNode(new HTCoordS(x, y));
		if (node != null)
		{
			return node.getName();
		}
		else
		{
			return null;
		}
	}

	boolean	antiAliasing		= true;
	boolean	qualityRendering	= false;

	/* --- Paint --- */

	/**
	 * Paint the component.
	 * 
	 * @param g
	 *            the graphic context
	 */
	@Override
	public void paintComponent(Graphics g)
	{
		Graphics2D castedGraphics = (Graphics2D) g;

		if (this.antiAliasing)
		{
			castedGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);
			castedGraphics.setRenderingHint(
					RenderingHints.KEY_TEXT_ANTIALIASING,
					RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		}
		else
		{
			castedGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_OFF);
			castedGraphics.setRenderingHint(
					RenderingHints.KEY_TEXT_ANTIALIASING,
					RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
		}

		if (this.qualityRendering)
		{
			castedGraphics.setRenderingHint(RenderingHints.KEY_RENDERING,
					RenderingHints.VALUE_RENDER_QUALITY);
			castedGraphics.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
					RenderingHints.VALUE_COLOR_RENDER_QUALITY);
			castedGraphics.setRenderingHint(
					RenderingHints.KEY_FRACTIONALMETRICS,
					RenderingHints.VALUE_FRACTIONALMETRICS_ON);
			castedGraphics.setRenderingHint(RenderingHints.KEY_DITHERING,
					RenderingHints.VALUE_DITHER_ENABLE);
		}
		else
		{
			castedGraphics.setRenderingHint(RenderingHints.KEY_RENDERING,
					RenderingHints.VALUE_RENDER_SPEED);
			castedGraphics.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
					RenderingHints.VALUE_COLOR_RENDER_SPEED);
			castedGraphics.setRenderingHint(
					RenderingHints.KEY_FRACTIONALMETRICS,
					RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
			castedGraphics.setRenderingHint(RenderingHints.KEY_DITHERING,
					RenderingHints.VALUE_DITHER_DISABLE);
		}

		super.paintComponent(castedGraphics);
		this.draw.refreshScreenCoordinates();
		this.draw.drawBranches(castedGraphics);
		this.draw.drawNodes(castedGraphics);
	}

	/* --- Thread-safe locking --- */

	/**
	 * Stops the listening of mouse events.
	 */
	void stopMouseListening()
	{
		this.removeMouseListener(this.action);
		this.removeMouseMotionListener(this.action);
	}

	/**
	 * Starts the listening of mouse events.
	 */
	void startMouseListening()
	{
		this.addMouseListener(this.action);
		this.addMouseMotionListener(this.action);
	}

}
